home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / python-support / gnome-games-data / glchess / chess / lan.py < prev    next >
Encoding:
Python Source  |  2009-04-14  |  5.7 KB  |  194 lines

  1. # -*- coding: utf-8 -*-
  2. """
  3. """
  4.  
  5. __author__ = 'Robert Ancell <bob27@users.sourceforge.net>'
  6. __license__ = 'GNU General Public License Version 2'
  7. __copyright__ = 'Copyright 2005-2006  Robert Ancell'
  8.  
  9. import board
  10.  
  11. CHECK        = '+'
  12. CHECKMATE    = '#'
  13.  
  14. # Notation for takes
  15. MOVE         = '-'
  16. TAKE         = 'x'
  17.  
  18. # Castling moves
  19. CASTLE_SHORT = 'o-o'
  20. CASTLE_LONG  = 'o-o-o'
  21.  
  22. # Characters used to describe pieces
  23. _typeToLAN = {board.PAWN:   'P',
  24.               board.KNIGHT: 'N',
  25.               board.BISHOP: 'B',
  26.               board.ROOK:   'R',
  27.               board.QUEEN:  'Q',
  28.               board.KING:   'K'}
  29. _lanToType = {}
  30. for (pieceType, character) in _typeToLAN.iteritems():
  31.     _lanToType[character] = pieceType
  32.     _lanToType[character.lower()] = pieceType # English pieces are sometimes written in lowercase
  33.  
  34. class DecodeError(Exception):
  35.     """
  36.     """
  37.     pass
  38.         
  39. def _checkLocation(location):
  40.     """
  41.     """
  42.     if len(location) != 2:
  43.         raise DecodeError('Invalid length location')
  44.     if location[0] < 'a' or location[0] > 'h':
  45.         raise DecodeError('Invalid rank')
  46.     if location[1] < '0' or location[1] > '8':
  47.         raise DecodeError('Invalid file')
  48.     return location
  49.  
  50. def decode(colour, move):
  51.     """Decode a long algebraic format move.
  52.     
  53.     'colour' is the colour of the player making the move (board.WHITE or board.BLACK).
  54.     'move' is the move description (string).
  55.  
  56.     Returns a tuple containing (start, end, piece, moveType, promotionType, result)
  57.     'start' is the location being moved from (string, e.g. 'a1', 'h8').
  58.     'end' is the location being moved to (string, e.g. 'a1', 'h8').
  59.     'piece' is the piece being moved (board.PAWN, board.ROOK, ... or None if not specified).
  60.     'moveType' is a flag to show if this move takes an oppoenent piece (MOVE, TAKE or None if not specified).
  61.     'promotionType' is the piece type to promote to (board.ROOK, board.KNIGHT, ... or None if not specified).
  62.     'check' is the result after the move (CHECK, CHECKMATE or None if not specified).
  63.     
  64.     Raises DecodeError if the move is unable to be decoded.
  65.     """
  66.     pieceType     = None
  67.     promotionType = None
  68.     moveType      = None
  69.     result        = None
  70.     
  71.     m = move
  72.     
  73.     if colour is board.WHITE:
  74.         baseFile = '1'
  75.     else:
  76.         baseFile = '8'
  77.     if m == CASTLE_SHORT:
  78.         return ('e' + baseFile, 'g' + baseFile, None, None, None, None)
  79.     elif m == CASTLE_LONG:
  80.         return ('e' + baseFile, 'c' + baseFile, None, None, None, None)
  81.  
  82.     # First character can be the piece types
  83.     if len(m) < 1:
  84.         raise DecodeError('Too short')
  85.     try:
  86.         pieceType = _lanToType[m[0]]
  87.     except KeyError:
  88.         pieceType = None
  89.     else:
  90.         m = m[1:]
  91.  
  92.     if len(m) < 2:
  93.         raise DecodeError('Too short')
  94.     try:
  95.         start = _checkLocation(m[:2])
  96.     except DecodeError, e:
  97.         if pieceType is None:
  98.             raise e
  99.         # Perhaps the first character wasn't a piece type
  100.         m = move
  101.         start = _checkLocation(m[:2])
  102.         pieceType = None
  103.     m = m[2:]
  104.         
  105.     if len(m) < 1:
  106.         raise DecodeError('Too short')
  107.     if m[0] == MOVE or m[0] == TAKE:
  108.         moveType = m[0]
  109.         m = m[1:]
  110.  
  111.     if len(m) < 2:
  112.         raise DecodeError('Too short')
  113.     end = _checkLocation(m[:2])
  114.     m = m[2:]
  115.  
  116.     # Look for promotion type, note this can be in upper or lower case
  117.     if len(m) > 0:
  118.         if m[0] == '=':
  119.             if len(m) < 2:
  120.                 raise DecodeError('Too short')
  121.             try:
  122.                 promotionType = _lanToType[m[1]]
  123.             except KeyError:
  124.                 raise DecodeError('Unknown promotion type')
  125.             m = m[2:]
  126.         else:
  127.             try:
  128.                 promotionType = _lanToType[m[0]]
  129.             except KeyError:
  130.                 pass
  131.             else:
  132.                 m = m[1:]
  133.  
  134.     if len(m) == 1:
  135.         if m == CHECK or m == CHECKMATE:
  136.             result = m
  137.             m = ''
  138.     elif len(m) == 2:
  139.         if m == '++':
  140.             result = CHECKMATE
  141.             m = ''
  142.  
  143.     if len(m) != 0:
  144.         raise DecodeError('Extra characters')
  145.     
  146.     return (start, end, pieceType, moveType, promotionType, result)
  147.  
  148. def encode(colour, start, end, piece = None, moveType = None, promotionType = None, result = None):
  149.     """Encode a long algebraic format move.
  150.         
  151.     'start' is the location being moved from (string, e.g. 'a1', 'h8').
  152.     'end' is the location being moved to (string, e.g. 'a1', 'h8').
  153.     'piece' is the piece being moved (board.PAWN, board.ROOK, ... or None if not specified).
  154.     'moveType' is a flag to show if this move takes an oppoenent piece (MOVE, TAKE or None if not specified).
  155.     'promotionType' is the piece type to promote to (board.ROOK, board.KNIGHT, ... or None if not specified).
  156.     'check' is the result after the move (CHECK, CHECKMATE or None if not specified).
  157.         
  158.     Returns a string describing this move.
  159.     """
  160.     try:
  161.         _checkLocation(start)
  162.         _checkLocation(end)
  163.     except DecodeError:
  164.         raise TypeError("Invalid values for 'start' and 'end'")
  165.         
  166.     string = ''
  167.         
  168.     # Report the piece being moved
  169.     if piece is not None:
  170.         string += _typeToLAN[piece]
  171.             
  172.     # Report the source location
  173.     string += start
  174.         
  175.     # Report if this is a move or a take
  176.     if moveType != None:
  177.         string += moveType
  178.  
  179.     # Report the target location
  180.     string += end
  181.         
  182.     # Report the promotion type
  183.     # FIXME: Only report if a pawn promotion
  184.     if promotionType != None:
  185.         if False: # FIXME: What to name this flag?
  186.             string += '='
  187.         string += _typeToLAN[promotionType].lower()
  188.  
  189.     # Report the check result
  190.     if result is not None:
  191.         string += result
  192.  
  193.     return string
  194.